package log;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

public class Logger implements ILog
{
	File[] m_currentLogs;
	private List<File[]> m_logs;
	private Integer m_logsCounter;
	private Writer[] m_outputs;
	private boolean logAvailable;
	
	//Constants
	private static final String LOG_NAME = "experimentLogs" + File.separator + "experimentLog_";
	private static final String BACKUP_LOG_NAME = "experimentLogs" + File.separator + "experimentBackupLog_";
	private static final String LOG_EXTENSION =".txt";
	private static final int LOG = 0;
	private static final int BACKUP_LOG = 1;
	
	/**
	 * C'tor
	 */
	public Logger()
	{
		m_logs = new ArrayList<File[]>();
		m_logsCounter = 0;
		m_currentLogs = new File[2];
		m_outputs = new Writer[2]; 
		logAvailable = false;
		File dir = new File("experimentLogs");
		if(!dir.exists())
		{
			dir.mkdir();
		}
	}

	@Override
	public void markEnd()
	{
		logAvailable = false;
		try
		{	
			m_outputs[LOG].close();
			m_outputs[BACKUP_LOG].close();
			
		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

	@Override
	public void markStart(String[] columnHeaders)
	{
		try{
			
			m_currentLogs = createLogs();		
			
			//save logs for later use
			m_logs.add(m_currentLogs);
			
			//create output
			m_outputs[LOG] = new BufferedWriter(new FileWriter(m_currentLogs[LOG]));
			m_outputs[BACKUP_LOG] = new BufferedWriter(new FileWriter(m_currentLogs[BACKUP_LOG]));
			
			writeSchema(columnHeaders);
			
			//always close backup log writer.
			m_outputs[BACKUP_LOG].close();
			
			logAvailable = true;
			
		}
		catch (IOException e)
		{
			logAvailable = false;  //no available logs for this experiment
		}
	}

	

	

	@Override
	public void writeLine(Object[] line)
	{
		if(logAvailable == false)
		{
			throw new RuntimeException("Logger.writeLine - no available log. did you forget markStart()?");
		}
		try 
		{
			StringBuilder sb = new StringBuilder();
			for(Object obj : line)
			{
				if(obj == null)
				{
					obj = new String("");
				}
				sb.append(obj.toString() + " , ");
				
			}
			sb.append("\n");
			
			m_outputs[LOG].write(sb.toString());
			m_outputs[LOG].flush();
			
			writeBackupLogLine(sb.toString());
		}
		catch (IOException e)
		{
			//ignore line
		}
		
	}
	
	private void writeBackupLogLine(String line)
	{
		try
		{
			m_outputs[BACKUP_LOG] = new BufferedWriter(new FileWriter(m_currentLogs[BACKUP_LOG] , true));
			m_outputs[BACKUP_LOG].write(line);
			m_outputs[BACKUP_LOG].flush();
			
			//always close backup log output writer
			m_outputs[BACKUP_LOG].close();
		} catch (IOException e)
		{
			//ignore line - writing to backup log failed
		}		
	}

	private File[] createLogs() throws IOException
	{
		++m_logsCounter; 
		File[] logs = new File[2];
		logs[LOG] = new File(LOG_NAME + m_logsCounter.toString() + LOG_EXTENSION);
		logs[BACKUP_LOG] = new File(BACKUP_LOG_NAME + m_logsCounter + LOG_EXTENSION);

		//create the files
		if(logs[LOG].exists())
		{
			logs[LOG].delete();
		}
		if(logs[BACKUP_LOG].exists())
		{
			logs[BACKUP_LOG].delete();
		}
		logs[LOG].createNewFile();
		logs[BACKUP_LOG].createNewFile();
		
		return logs;
	}
	
	private void writeSchema(String[] columnHeaders) throws IOException
	{
		StringBuilder sb = new StringBuilder();
		for(String header : columnHeaders)
		{
			sb.append(header + " , ");
		}
		sb.append("\n");
		
		m_outputs[LOG].write(sb.toString());
		m_outputs[BACKUP_LOG].write(sb.toString());
		
		m_outputs[LOG].flush();
		m_outputs[BACKUP_LOG].flush();
	}
	

}
